github.com/quinndk/ethereum_read@v0.0.0-20181211143958-29c55eec3237/Docs/0xa0 EVM机制 .md (about)

     1  # 0xa0 EVM机制 
     2  
     3  EVM,Ethereum Virtual Machine,以太坊虚拟机。它是以太坊智能合约的运行环境。我们知道之前我们写简单的智能合约时都需要将solidlity代码编译形成字节码才能够部署到以太坊上。同时在交易模块讲了一笔交易的大概流程,但是对于交易的真正执行并没有涉及到,其实交易的执行也是依赖于EVM。
     4  
     5  # 原理
     6  
     7  EVM本质上是一个堆栈机器,最直接的功能就是执行 智能合约。关于其定义,[官档](https://solidity.readthedocs.io/en/v0.4.24/introduction-to-smart-contracts.html#index-6)给出的叙述是这样的:
     8  
     9  > The Ethereum Virtual Machine or EVM is the runtime environment for smart contracts in Ethereum. It is not only sandboxed but actually completely isolated, which means that code running inside the EVM has no access to network, filesystem or other processes. Smart contracts even have limited access to other smart contracts.
    10  以太坊虚拟机或EVM是以太坊中智能合约的运行时环境。 它不仅仅是沙箱,而且实际上是完全隔离的,这意味着EVM无法访问网络,文件系统或其他进程。 智能合约甚至可以限制其他智能合约的使用。
    11  
    12  接着官档介绍了有关EVM的一些诸如Account,Gas等概念的介绍 ,都是之前接触过的在此略过不提。这里着重看一下EVM的存储系统和其他几个重要的概念。
    13  
    14  ### 存储系统
    15  EVM机器位宽为256位,即32个字节,256位机器字宽不同于我们经常见到主流的64位的机器字宽,这就表明EVM设计上将考虑一套自己的关于操作,数据,逻辑控制的指令编码。目前主流的处理器原生支持的计算数据类型有:8bits整数,16bits整数,32bits整数,64bits整数。
    16  
    17  EVM中每个账户有一块持久化内存区称为 存储 。存储是将256位字映射到256位的键值存储区。 在合约中枚举存储是不可能的,且读存储的相对开销很高,修改存储的开销甚至更高。合约只能读写存储区内属于自己的部分。
    18  
    19  第二个内存区域称为内存,合约每次调用会获取一块被清除确保没有脏数据的内存。存储器是线性的,可以在字节级读取,但读取限制为256位宽,而写操作可以是8位或256位宽。当访问(读取或写入)先前未访问过的存储器字(字内的任何偏移)时,存储器会按字(256位)进行扩展。扩容会消耗一定的Gas。随着内存的增大,内存成本越高(二次方指数增长)。
    20  
    21  EVM不是基于寄存器的,而是基于栈机器,因此所有计算都在栈上执行。栈的容量为1024,每个元素是一个包含256位的字。可以将最顶部的16个元素之一复制到栈顶,或者将最顶层的元素与其下面的16个元素之一交换。所有其他操作只能从栈中取最顶部的两个(或一个或多个,取决于操作)元素进行运算,然后压栈道栈顶。
    22  
    23  ### Instruction Set指令集
    24  
    25  EVM的指令集量应尽量少,以最大限度地避免可能导致共识问题的错误实现。所有的指令都是针对”256位的字(word)”这个基本的数据类型来进行操作。具备常用的算术、位、逻辑和比较操作。也可以做到有条件和无条件跳转。此外,合约可以访问当前区块的相关属性,比如它的编号和时间戳。
    26  
    27  ### Message Calls消息调用
    28  
    29  合约可以通过消息调用的方式来调用其它合约或者发送以太币到非合约账户。消息调用和交易非常类似,它们都有一个源、目标、数据、以太币、gas和返回数据。事实上每个交易都由一个顶层消息调用组成,这个消息调用又可创建更多的消息调用。
    30  
    31  合约可以决定在其内部的消息调用中,对于剩余的 gas ,应发送和保留多少。如果在内部消息调用时发生了out-of-gas异常(或其他任何异常),这将由一个被压入栈顶的错误值所指明。此时,只有与该内部消息调用一起发送的gas会被消耗掉。并且,Solidity中,发起调用的合约默认会触发一个手工的异常,以便异常可以从调用栈里“冒泡出来”。
    32  
    33   如前文所述,被调用的合约(可以和调用者是同一个合约)会获得一块刚刚清空过的内存,并可以访问调用的payload——由被称为 calldata 的独立区域所提供的数据。调用执行结束后,返回数据将被存放在调用方预先分配好的一块内存中。 调用深度被 限制 为 1024 ,因此对于更加复杂的操作,我们应 使用循环而不是递归。
    34  
    35  ### Delegatecall / Callcode and Libraries 委托调用和代码调用库
    36  
    37  Delegatecall是EVM中一种特殊的消息调用,它与普通消息调用的区别在于:目标地址的代码将在发起调用的合约的上下文中执行,并且 msg.sender 和 msg.value 不变。这就意味着合约可以在运行时从不同的地址动态加载代码。存储、当前地址和余额都指向发起调用的合约,只有代码是从被调用地址获取的。
    38  
    39  如此就使得Solidity实现"库调用"成为可能,于是就出现了可复用的代码调用库。
    40  
    41  ### Logs日志
    42  
    43  Logs是一直能够特殊的可索引的数据结构,其存储的数据可以一直映射到区块层级,Solidity借助它来实现事件(Events)。
    44  
    45  智能合约一经创建就无法访问Logs,但Logs可以从区块链外有效地访问。部分Logs数据被存储在Bloom filter(布隆过滤器)中,因此可以以高效且加密的方式搜索此数据,也是因为这样那些没有下载全节点的轻客户端也能够访问这些数据。
    46  
    47  ### Create & Self-destruct 智能合约的创建和销毁
    48  
    49  智能合约甚至可以通过特殊的指令来创建其他合约(并不是简单地调用零地址)。这种创建合约的消息调用和普通消息调用的区别在于,负载会被执行并且执行结果会被存储为合约代码,同时将新合约地址返回给调用者。
    50  
    51  智能合约代码从区块链上移除的唯一方式是合约在合约地址上执行自毁操作selfdestruct。存储在合约上的以太币会发送给指定账户,然后从状态中移除存储和代码。尽管一个合约没有显式地调用selfdestruct,它依然可以通过delegatecall或callcode来间接地执行自毁操作。
    52  
    53  咳咳…连蒙带猜加上谷译的助攻终于将官档看完了,以上都是个人所读仅供参考以达抛砖引玉之用,大佬们深入理解一切还是要以官档原文为准的。
    54  
    55  # 源码撸起来
    56  
    57  ### 高屋建瓴总览大局
    58  
    59  了解几本原理后,就可以从源码入手来分析下EVM的运行机制。首先来看看源码vm相关的目录结构:
    60  
    61  ```
    62  ➜  vm pwd
    63  /Users/chaors/BlockChain/ethereum/SourceCodeRead/go-ethereum-master_read/core/vm
    64  ➜  vm tree
    65  .
    66  |____memory.go                    //EVM内存
    67  |____opcodes.go                   //op指令集
    68  |____analysis.go                  //跳转目标判断
    69  |____gas_table_test.go      
    70  |____gas_table.go                 //指令耗费gas计算表
    71  |____evm.go                       //evm对外接口
    72  |____gas.go                       //gas花费计算
    73  |____intpool_test.go
    74  |____logger.go                    //evm日志
    75  |____int_pool_verifier_empty.go
    76  |____runtime
    77  | |____env.go                     //执行环境
    78  | |____runtime.go                 //运行时
    79  | |____runtime_example_test.go
    80  | |____doc.go
    81  | |____runtime_test.go
    82  | |____fuzz.go
    83  |____interface.go
    84  |____analysis_test.go
    85  |____instructions.go              //指令集实现
    86  |____gen_structlog.go
    87  |____contracts.go                 //预编译的合约
    88  |____memory_table.go              //evm内存操作表
    89  |____noop.go
    90  |____instructions_test.go
    91  |____doc.go
    92  |____stack.go                     //栈
    93  |____common.go                    //一些共有方法
    94  |____stack_table.go               //栈验证表
    95  |____interpreter.go               //解释器
    96  |____intpool.go                   //int值存储池
    97  |____jump_table.go                //指令和指令操作对应表
    98  |____contract.go                  //智能合约
    99  |____int_pool_verifier.go
   100  |____contracts_test.go
   101  |____logger_test.go
   102  |____errors.go                    //错误类
   103  ```
   104  
   105  ### EVM结构
   106  
   107  ```
   108  type Context struct {
   109  	// CanTransfer returns whether the account contains
   110  	// sufficient ether to transfer the value
   111  	// 返回账户是否包含足够的用来传输的以太币
   112  	CanTransfer CanTransferFunc
   113  	// Transfer transfers ether from one account to the other
   114  	// 将以太从一个帐户转移到另一个帐户
   115  	Transfer TransferFunc
   116  	// GetHash returns the hash corresponding to n
   117  	GetHash GetHashFunc
   118  
   119  	// Message information
   120  	// 消息相关信息
   121  	Origin   common.Address // Provides information for ORIGIN
   122  	GasPrice *big.Int       // Provides information for GASPRICE
   123  
   124  	// Block information
   125  	// 区块相关信息
   126  	Coinbase    common.Address // Provides information for COINBASE
   127  	GasLimit    uint64         // Provides information for GASLIMIT
   128  	BlockNumber *big.Int       // Provides information for NUMBER
   129  	Time        *big.Int       // Provides information for TIME
   130  	Difficulty  *big.Int       // Provides information for DIFFICULTY
   131  }
   132  
   133  // EVM is the Ethereum Virtual Machine base object and provides
   134  // the necessary tools to run a contract on the given state with
   135  // the provided context. It should be noted that any error
   136  // generated through any of the calls should be considered a
   137  // revert-state-and-consume-all-gas operation, no checks on
   138  // specific errors should ever be performed. The interpreter makes
   139  // sure that any errors generated are to be considered faulty code.
   140  //
   141  // The EVM should never be reused and is not thread safe.
   142  // // EVM是以太坊虚拟机基础对象,并提供必要的工具,以使用提供的上下文运行给定状态的合约。
   143  // 应该指出的是,任何调用产生的任何错误都应该被认为是一种回滚修改状态和消耗所有GAS操作,
   144  // 不应该执行对具体错误的检查。 解释器确保生成的任何错误都被认为是错误的代码。
   145  type EVM struct {
   146  	// Context provides auxiliary blockchain related information
   147  	// 辅助信息对象(包括GasPrice,GasLimit,BlockNumber等信息)
   148  	Context
   149  	// StateDB gives access to the underlying state
   150  	// 为EVM提供StateDB相关操作
   151  	StateDB StateDB
   152  	// Depth is the current call stack
   153  	// 当前调用的栈
   154  	depth int
   155  
   156  	// chainConfig contains information about the current chain
   157  	// 链配置信息
   158  	chainConfig *params.ChainConfig
   159  	// chain rules contains the chain rules for the current epoch
   160  	// 链规则
   161  	chainRules params.Rules
   162  	// virtual machine configuration options used to initialise the
   163  	// evm.
   164  	// 虚拟机配置
   165  	vmConfig Config
   166  	// global (to this context) ethereum virtual machine
   167  	// used throughout the execution of the tx.
   168  	// 解释器
   169  	interpreter *Interpreter
   170  	// abort is used to abort the EVM calling operations
   171  	// NOTE: must be set atomically
   172  	// 用于中止EVM调用操作
   173  	abort int32
   174  	// callGasTemp holds the gas available for the current call. This is needed because the
   175  	// available gas is calculated in gasCall* according to the 63/64 rule and later
   176  	// applied in opCall*.
   177  	// 当前call可用的gas
   178  	callGasTemp uint64
   179  }
   180  
   181  // NewEVM returns a new EVM. The returned EVM is not thread safe and should
   182  // only ever be used *once*.
   183  func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
   184  	evm := &EVM{
   185  		Context:     ctx,
   186  		StateDB:     statedb,
   187  		vmConfig:    vmConfig,
   188  		chainConfig: chainConfig,
   189  		chainRules:  chainConfig.Rules(ctx.BlockNumber),
   190  	}
   191  
   192  	evm.interpreter = NewInterpreter(evm, vmConfig)
   193  	return evm
   194  }
   195  ```
   196  
   197  ### Contract结构
   198  既然EVM最直接的功能就是运行智能合约,接下来就看看智能合约的数据结构。
   199  
   200  ```
   201  // Contract represents an ethereum contract in the state database. It contains
   202  // the the contract code, calling arguments. Contract implements ContractRef
   203  // 数据库中的以太坊智能合约,包括合约代码和调用参数
   204  type Contract struct {
   205  	// CallerAddress is the result of the caller which initialised this
   206  	// contract. However when the "call method" is delegated this value
   207  	// needs to be initialised to that of the caller's caller.
   208  	// 合约调用者
   209  	CallerAddress common.Address
   210  	caller        ContractRef
   211  	self          ContractRef
   212  
   213  	// JUMPDEST分析的结果
   214  	jumpdests destinations // result of JUMPDEST analysis.
   215  
   216  	// 合约代码
   217  	Code     []byte
   218  	CodeHash common.Hash
   219  	// 合约地址
   220  	CodeAddr *common.Address
   221  	Input    []byte
   222  
   223  	Gas   uint64
   224  	value *big.Int
   225  
   226  	Args []byte
   227  
   228  	// 是否委托调用
   229  	DelegateCall bool
   230  }
   231  
   232  // NewContract returns a new contract environment for the execution of EVM.
   233  // 为EVM创建合约环境
   234  func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
   235  	c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
   236  
   237  	if parent, ok := caller.(*Contract); ok {
   238  		// Reuse JUMPDEST analysis from parent context if available.
   239  		c.jumpdests = parent.jumpdests
   240  	} else {
   241  		c.jumpdests = make(destinations)
   242  	}
   243  
   244  	// Gas should be a pointer so it can safely be reduced through the run
   245  	// This pointer will be off the state transition
   246  	c.Gas = gas
   247  	// ensures a value is set
   248  	c.value = value
   249  
   250  	return c
   251  }
   252  ```
   253  
   254  ### EVM工作逻辑
   255  
   256  EVM运行的大概逻辑是这样的:
   257  
   258  - __1.创建EVM运行的上下文环境,同时实例化一个EVM对象__
   259  
   260  - __2.合约不存在则创建新合约,使用已经存在的合约则世界调用call__
   261  
   262  - __3.EVM通过interpreter解释器来执行智能合约__
   263  
   264  创建EVM对象的代码:
   265  
   266  ```
   267  // NewEVMContext creates a new context for use in the EVM.
   268  // 1.创建EVM上下文环境
   269  func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) vm.Context {
   270  	// If we don't have an explicit author (i.e. not mining), extract from the header
   271  	// 如果不挖矿,受益人从区块头中提取
   272  	var beneficiary common.Address
   273  	if author == nil {
   274  		beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation
   275  	} else {
   276  		beneficiary = *author
   277  	}
   278  	return vm.Context{
   279  		CanTransfer: CanTransfer,
   280  		Transfer:    Transfer,
   281  		GetHash:     GetHashFn(header, chain),
   282  		Origin:      msg.From(),
   283  		Coinbase:    beneficiary,
   284  		BlockNumber: new(big.Int).Set(header.Number),
   285  		Time:        new(big.Int).Set(header.Time),
   286  		Difficulty:  new(big.Int).Set(header.Difficulty),
   287  		GasLimit:    header.GasLimit,
   288  		GasPrice:    new(big.Int).Set(msg.GasPrice()),
   289  	}
   290  }
   291  ...
   292  // NewEVM returns a new EVM. The returned EVM is not thread safe and should
   293  // only ever be used *once*.
   294  // 2.创建EVM对象
   295  func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
   296  	evm := &EVM{
   297  		Context:     ctx,
   298  		StateDB:     statedb,
   299  		vmConfig:    vmConfig,
   300  		chainConfig: chainConfig,
   301  		chainRules:  chainConfig.Rules(ctx.BlockNumber),
   302  	}
   303  
   304  	// 3.创建EVM解释器
   305  	evm.interpreter = NewInterpreter(evm, vmConfig)
   306  	return evm
   307  }
   308  ...
   309  // NewInterpreter returns a new instance of the Interpreter.
   310  // 3.创建解释器
   311  func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
   312  	// We use the STOP instruction whether to see
   313  	// the jump table was initialised. If it was not
   314  	// we'll set the default jump table.
   315  	if !cfg.JumpTable[STOP].valid {
   316  		switch {
   317  		case evm.ChainConfig().IsConstantinople(evm.BlockNumber):
   318  			cfg.JumpTable = constantinopleInstructionSet
   319  		case evm.ChainConfig().IsByzantium(evm.BlockNumber):
   320  			cfg.JumpTable = byzantiumInstructionSet
   321  		case evm.ChainConfig().IsHomestead(evm.BlockNumber):
   322  			cfg.JumpTable = homesteadInstructionSet
   323  		default:
   324  			cfg.JumpTable = frontierInstructionSet
   325  		}
   326  	}
   327  
   328  	return &Interpreter{
   329  		evm:      evm,
   330  		cfg:      cfg,
   331  		gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
   332  	}
   333  }
   334  ```
   335  
   336  创建合约的代码
   337  
   338  ```
   339  // Create creates a new contract using code as deployment code.
   340  // 创建合约
   341  func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   342  
   343  	// Depth check execution. Fail if we're trying to execute above the
   344  	// limit.
   345  	// 执行深度检查,如果超出设定的深度限制  创建失败
   346  	if evm.depth > int(params.CallCreateDepth) {
   347  		return nil, common.Address{}, gas, ErrDepth
   348  	}
   349  	// 账户余额不足,创建失败
   350  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   351  		return nil, common.Address{}, gas, ErrInsufficientBalance
   352  	}
   353  	// Ensure there's no existing contract already at the designated address
   354  	// 确保指定地址没有已存在的相同合约
   355  	nonce := evm.StateDB.GetNonce(caller.Address())
   356  	evm.StateDB.SetNonce(caller.Address(), nonce+1)
   357  
   358  	// 创建合约地址
   359  	contractAddr = crypto.CreateAddress(caller.Address(), nonce)
   360  	contractHash := evm.StateDB.GetCodeHash(contractAddr)
   361  	if evm.StateDB.GetNonce(contractAddr) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
   362  		return nil, common.Address{}, 0, ErrContractAddressCollision
   363  	}
   364  	// Create a new account on the state
   365  	// 创建数据库快照,为了迅速回滚
   366  	snapshot := evm.StateDB.Snapshot()
   367  	// 在当前状态新建合约账户
   368  	evm.StateDB.CreateAccount(contractAddr)
   369  	if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
   370  		evm.StateDB.SetNonce(contractAddr, 1)
   371  	}
   372  	// 转账操作
   373  	evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value)
   374  
   375  	// initialise a new contract and set the code that is to be used by the
   376  	// EVM. The contract is a scoped environment for this execution context
   377  	// only.
   378  	// 创建合约
   379  	contract := NewContract(caller, AccountRef(contractAddr), value, gas)
   380  	// 设置合约代码
   381  	contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
   382  
   383  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   384  		return nil, contractAddr, gas, nil
   385  	}
   386  
   387  	if evm.vmConfig.Debug && evm.depth == 0 {
   388  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), contractAddr, true, code, gas, value)
   389  	}
   390  	start := time.Now()
   391  
   392  	// 执行合约的初始化
   393  	ret, err = run(evm, contract, nil)
   394  
   395  	// check whether the max code size has been exceeded
   396  	// 检查初始化生成的代码长度是否超过限制
   397  	maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize
   398  	// if the contract creation ran successfully and no errors were returned
   399  	// calculate the gas required to store the code. If the code could not
   400  	// be stored due to not enough gas set an error and let it be handled
   401  	// by the error checking condition below.
   402  	// 合约创建成功
   403  	if err == nil && !maxCodeSizeExceeded {
   404  		// 计算存储代码所需要的Gas
   405  		createDataGas := uint64(len(ret)) * params.CreateDataGas
   406  		if contract.UseGas(createDataGas) {
   407  			evm.StateDB.SetCode(contractAddr, ret)
   408  		} else {
   409  			// 当前拥有的Gas不足以存储代码
   410  			err = ErrCodeStoreOutOfGas
   411  		}
   412  	}
   413  
   414  	// When an error was returned by the EVM or when setting the creation code
   415  	// above we revert to the snapshot and consume any gas remaining. Additionally
   416  	// when we're in homestead this also counts for code storage gas errors.
   417  	// 合约创建失败,借助上面创建的快照快速回滚
   418  	if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
   419  		evm.StateDB.RevertToSnapshot(snapshot)
   420  		if err != errExecutionReverted {
   421  			contract.UseGas(contract.Gas)
   422  		}
   423  	}
   424  	// Assign err if contract code size exceeds the max while the err is still empty.
   425  	if maxCodeSizeExceeded && err == nil {
   426  		err = errMaxCodeSizeExceeded
   427  	}
   428  	if evm.vmConfig.Debug && evm.depth == 0 {
   429  		evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   430  	}
   431  	return ret, contractAddr, contract.Gas, err
   432  }
   433  ...
   434  // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
   435  func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
   436  	if contract.CodeAddr != nil {
   437  		precompiles := PrecompiledContractsHomestead
   438  		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
   439  			precompiles = PrecompiledContractsByzantium
   440  		}
   441  		if p := precompiles[*contract.CodeAddr]; p != nil {
   442  			// 运行预编译合约
   443  			return RunPrecompiledContract(p, input, contract)
   444  		}
   445  	}
   446  	// 解释器执行合约代码
   447  	return evm.interpreter.Run(contract, input)
   448  }
   449  ```
   450  
   451  这里合约代码的执行后续再看,当调用已创建的合约时,使用的是call方法。Call方法和create方法的逻辑大体相同,这里分析下他们的不同之处:
   452  
   453  - 1.call调用的是一个已经存在合约账户的合约,create是新建一个合约账户。
   454  
   455  - 2.call里evm.Transfer发生在合约的发送方和接收方,create里则是创建合约用户的账户和该合约用户之间。
   456  
   457  ```
   458  // Call executes the contract associated with the addr with the given input as
   459  // parameters. It also handles any necessary value transfer required and takes
   460  // the necessary steps to create accounts and reverses the state in case of an
   461  // execution error or failed value transfer.
   462  // 使用给定输入作为参数执行与addr关联的合约
   463  func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   464  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   465  		return nil, gas, nil
   466  	}
   467  
   468  	// Fail if we're trying to execute above the call depth limit
   469  	if evm.depth > int(params.CallCreateDepth) {
   470  		return nil, gas, ErrDepth
   471  	}
   472  	// Fail if we're trying to transfer more than the available balance
   473  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   474  		return nil, gas, ErrInsufficientBalance
   475  	}
   476  
   477  	var (
   478  		to       = AccountRef(addr)
   479  		snapshot = evm.StateDB.Snapshot()
   480  	)
   481  	if !evm.StateDB.Exist(addr) {
   482  		precompiles := PrecompiledContractsHomestead
   483  		if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
   484  			precompiles = PrecompiledContractsByzantium
   485  		}
   486  		if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
   487  			// Calling a non existing account, don't do antything, but ping the tracer
   488  			if evm.vmConfig.Debug && evm.depth == 0 {
   489  				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   490  				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
   491  			}
   492  			return nil, gas, nil
   493  		}
   494  		evm.StateDB.CreateAccount(addr)
   495  	}
   496  	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
   497  
   498  	// Initialise a new contract and set the code that is to be used by the EVM.
   499  	// The contract is a scoped environment for this execution context only.
   500  	contract := NewContract(caller, to, value, gas)
   501  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   502  
   503  	start := time.Now()
   504  
   505  	// Capture the tracer start/end events in debug mode
   506  	if evm.vmConfig.Debug && evm.depth == 0 {
   507  		evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
   508  
   509  		defer func() { // Lazy evaluation of the parameters
   510  			evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
   511  		}()
   512  	}
   513  	ret, err = run(evm, contract, input)
   514  
   515  	// When an error was returned by the EVM or when setting the creation code
   516  	// above we revert to the snapshot and consume any gas remaining. Additionally
   517  	// when we're in homestead this also counts for code storage gas errors.
   518  	if err != nil {
   519  		evm.StateDB.RevertToSnapshot(snapshot)
   520  		if err != errExecutionReverted {
   521  			contract.UseGas(contract.Gas)
   522  		}
   523  	}
   524  	return ret, contract.Gas, err
   525  }
   526  ```
   527  
   528  ### DelegateCall
   529  
   530  上面阅读官档时,涉及到一个DelegateCall委托调用的概念。上面看的Call函数便是便是普通的消息调用,接下来看看EVM中几个特殊的消息调用。这里只讲它们的特殊之处,代码逻辑和Call大体相同,源码就不再看了,参考Call即可。
   531  
   532  - CallCode,它与Call不同的地方在于它使用调用者的EVMContext来执行给定地址的合约代码。
   533  
   534  - DelegateCall,它与CallCode不同的地方在于它调用者被设置为调用者的调用者
   535  
   536  - StaticCall,它不允许执行任何状态的修改
   537  
   538  - 以上三个特殊的消息调用只能由opcode触发,它们不像Call可以由外部调用。
   539  
   540  ### Interpreter EVM解释器
   541  
   542  合约的执行最终是靠解释器Interpreter来实现的,这里就来看看Interpreter的数据结构。
   543  
   544  ```
   545  // Config are the configuration options for the Interpreter
   546  // 解释器配置类
   547  type Config struct {
   548  	// Debug enabled debugging Interpreter options
   549  	// 启用调试
   550  	Debug bool
   551  	// Tracer is the op code logger
   552  	// 操作码记录器
   553  	Tracer Tracer
   554  	// NoRecursion disabled Interpreter call, callcode,
   555  	// delegate call and create.
   556  	// 禁用解释器调用,代码库调用,委托调用
   557  	NoRecursion bool
   558  	// Enable recording of SHA3/keccak preimages
   559  	// 启用SHA3/keccak
   560  	EnablePreimageRecording bool
   561  	// JumpTable contains the EVM instruction table. This
   562  	// may be left uninitialised and will be set to the default
   563  	// table.
   564  	// 操作码opcode对应的操作表
   565  	JumpTable [256]operation
   566  }
   567  
   568  // Interpreter is used to run Ethereum based contracts and will utilise the
   569  // passed environment to query external sources for state information.
   570  // The Interpreter will run the byte code VM based on the passed
   571  // configuration.
   572  // 用来运行智能合约的字节码
   573  type Interpreter struct {
   574  	evm      *EVM
   575  	// 解释器配置
   576  	cfg      Config
   577  	// gas价格表,根据不同的以太坊阶段来决定
   578  	gasTable params.GasTable
   579  	intPool  *intPool
   580  
   581  	readOnly   bool   // Whether to throw on stateful modifications
   582  	// 最后一个call调用的返回值
   583  	returnData []byte // Last CALL's return data for subsequent reuse
   584  }
   585  ```
   586  
   587  接着继续看它是怎么实现智能合约的执行的。
   588  
   589  ```
   590  // Run loops and evaluates the contract's code with the given input data and returns
   591  // the return byte-slice and an error if one occurred.
   592  //
   593  // It's important to note that any errors returned by the interpreter should be
   594  // considered a revert-and-consume-all-gas operation except for
   595  // errExecutionReverted which means revert-and-keep-gas-left.
   596  // 执行合约代码
   597  func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) {
   598  	if in.intPool == nil {
   599  		in.intPool = poolOfIntPools.get()
   600  		defer func() {
   601  			poolOfIntPools.put(in.intPool)
   602  			in.intPool = nil
   603  		}()
   604  	}
   605  
   606  	// Increment the call depth which is restricted to 1024
   607  	// 调用深度递增,evm执行栈的深度不能超过1024
   608  	in.evm.depth++
   609  	defer func() { in.evm.depth-- }()
   610  
   611  	// Reset the previous call's return data. It's unimportant to preserve the old buffer
   612  	// as every returning call will return new data anyway.
   613  	// 重置上一个call的返回数据
   614  	in.returnData = nil
   615  
   616  	// Don't bother with the execution if there's no code.
   617  	// 合约代码为空
   618  	if len(contract.Code) == 0 {
   619  		return nil, nil
   620  	}
   621  
   622  	var (
   623  		op    OpCode        // current opcode
   624  		mem   = NewMemory() // bound memory
   625  		stack = newstack()  // local stack
   626  		// For optimisation reason we're using uint64 as the program counter.
   627  		// It's theoretically possible to go above 2^64. The YP defines the PC
   628  		// to be uint256. Practically much less so feasible.
   629  		pc   = uint64(0) // program counter
   630  		cost uint64
   631  		// copies used by tracer
   632  		pcCopy  uint64 // needed for the deferred Tracer
   633  		gasCopy uint64 // for Tracer to log gas remaining before execution
   634  		logged  bool   // deferred Tracer should ignore already logged steps
   635  	)
   636  	contract.Input = input
   637  
   638  	// Reclaim the stack as an int pool when the execution stops
   639  	// 执行停止时将栈回收为int值缓存池
   640  	defer func() { in.intPool.put(stack.data...) }()
   641  
   642  	if in.cfg.Debug {
   643  		defer func() {
   644  			if err != nil {
   645  				if !logged {
   646  					in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
   647  				} else {
   648  					in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
   649  				}
   650  			}
   651  		}()
   652  	}
   653  	// The Interpreter main run loop (contextual). This loop runs until either an
   654  	// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
   655  	// the execution of one of the operations or until the done flag is set by the
   656  	// parent context.
   657  	// 解释器主循环,循环运行直到执行显式STOP,RETURN或SELFDESTRUCT,发生错误
   658  	for atomic.LoadInt32(&in.evm.abort) == 0 {
   659  		if in.cfg.Debug {
   660  			// Capture pre-execution values for tracing.
   661  			// 捕获预执行的值进行跟踪
   662  			logged, pcCopy, gasCopy = false, pc, contract.Gas
   663  		}
   664  
   665  		// Get the operation from the jump table and validate the stack to ensure there are
   666  		// enough stack items available to perform the operation.
   667  		// 从合约的二进制数据i获取第pc个opcode操作符 opcode是以太坊虚拟机指令,一共不超过256个,正好一个byte大小能装下
   668  		op = contract.GetOp(pc)
   669  		// 从JumpTable表中查询op对应的操作
   670  		operation := in.cfg.JumpTable[op]
   671  		if !operation.valid {
   672  			return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
   673  		}
   674  		if err := operation.validateStack(stack); err != nil {
   675  			return nil, err
   676  		}
   677  		// If the operation is valid, enforce and write restrictions
   678  		// 操作有效,强制执行
   679  		if err := in.enforceRestrictions(op, operation, stack); err != nil {
   680  			return nil, err
   681  		}
   682  
   683  		var memorySize uint64
   684  		// calculate the new memory size and expand the memory to fit
   685  		// the operation
   686  		// 计算新的内存大小以适应操作,必要时进行扩容
   687  		if operation.memorySize != nil {
   688  			// memSize不能大于64位
   689  			memSize, overflow := bigUint64(operation.memorySize(stack))
   690  			if overflow {
   691  				return nil, errGasUintOverflow
   692  			}
   693  			// memory is expanded in words of 32 bytes. Gas
   694  			// is also calculated in words.
   695  			// 扩容按32字节的字扩展
   696  			if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
   697  				return nil, errGasUintOverflow
   698  			}
   699  		}
   700  		// consume the gas and return an error if not enough gas is available.
   701  		// cost is explicitly set so that the capture state defer method can get the proper cost
   702  		// 计算执行操作所需要的gas
   703  		cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
   704  		// gas不足
   705  		if err != nil || !contract.UseGas(cost) {
   706  			return nil, ErrOutOfGas
   707  		}
   708  		if memorySize > 0 {
   709  			mem.Resize(memorySize)
   710  		}
   711  
   712  		if in.cfg.Debug {
   713  			in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
   714  			logged = true
   715  		}
   716  
   717  		// execute the operation
   718  		// 执行操作
   719  		res, err := operation.execute(&pc, in.evm, contract, mem, stack)
   720  		// verifyPool is a build flag. Pool verification makes sure the integrity
   721  		// of the integer pool by comparing values to a default value.
   722  		// 验证int值缓存池
   723  		if verifyPool {
   724  			verifyIntegerPool(in.intPool)
   725  		}
   726  		// if the operation clears the return data (e.g. it has returning data)
   727  		// set the last return to the result of the operation.
   728  		// 将最后一次返回设为操作结果
   729  		if operation.returns {
   730  			in.returnData = res
   731  		}
   732  
   733  		switch {
   734  		case err != nil:
   735  			return nil, err
   736  		case operation.reverts:
   737  			return res, errExecutionReverted
   738  		case operation.halts:
   739  			return res, nil
   740  		case !operation.jumps:
   741  			pc++
   742  		}
   743  	}
   744  	return nil, nil
   745  }
   746  ```
   747  
   748  ### JumpTable(opCode-operation)
   749  
   750  在执行合约的时候涉及到contract.GetOp(pc)方法从合约二进制代码中取出第pc个操作符opcode,然后再按对应关系找到opcode对应的操作operation。这里的对应关系就保存在jump_table中。
   751  
   752  这里先要理解操作符opcode的概念,它是EVM的操作符。通俗地讲,一个opcode就是一个byte,solidity合约编译形成的bytecode中,一个byte就代表一个opcode。opcodes.go中定义了所有的操作符,并将所有的操作符按功能分类。例如下面是一组块操作相关的操作符:
   753  
   754  ```
   755  // 0x40 range - block operations.
   756  const (
   757  	BLOCKHASH OpCode = 0x40 + iota
   758  	COINBASE
   759  	TIMESTAMP
   760  	NUMBER
   761  	DIFFICULTY
   762  	GASLIMIT
   763  )
   764  ```
   765  
   766  每一个opcode都会对应一个具体的操作operation,一个操作包含其操作函数以及一些必要的参数。
   767  
   768  ```
   769  type operation struct {
   770  	// execute is the operation function
   771  	// 操作函数
   772  	execute executionFunc
   773  	// gasCost is the gas function and returns the gas required for execution
   774  	// 计算操作需要多少gas的函数
   775  	gasCost gasFunc
   776  	// validateStack validates the stack (size) for the operation
   777  	// 验证操作的栈
   778  	validateStack stackValidationFunc
   779  	// memorySize returns the memory size required for the operation
   780  	// 操作需要的内存大小
   781  	memorySize memorySizeFunc
   782  
   783  	// 操作终止
   784  	halts   bool // indicates whether the operation should halt further execution
   785  	// 操作跳转
   786  	jumps   bool // indicates whether the program counter should not increment
   787  	// 是否写入
   788  	writes  bool // determines whether this a state modifying operation
   789  	// 操作是否有效
   790  	valid   bool // indication whether the retrieved operation is valid and known
   791  	// 出错回滚
   792  	reverts bool // determines whether the operation reverts state (implicitly halts)
   793  	// 操作返回
   794  	returns bool // determines whether the operations sets the return data content
   795  }
   796  ```
   797  
   798  opcode和operation的对应关系都在jump_table.go中。例如我们上面举例的相关块操作的操作符,这里以EXTCODECOPY(0x3d)操作符为例:
   799  
   800  ```
   801  EXTCODECOPY: {
   802  			execute:       opExtCodeCopy,
   803  			gasCost:       gasExtCodeCopy,
   804  			validateStack: makeStackFunc(4, 0),
   805  			memorySize:    memoryExtCodeCopy,
   806  			valid:         true,
   807  		},
   808  ```
   809  
   810  针对每一个具体的操作operation,其内部属性对应的实现代码为:
   811  
   812  - execute---instructions.go,例如上面里的opExtCodeCopy
   813  
   814  - gasCost---gas_table.go, 例如上面里的gasExtCodeCopy
   815  
   816  - validateStack---stack_table,例如上面里的makeStackFunc
   817  
   818  - memorySize---memory_table.go,例如上面里的memoryExtCodeCopy
   819  
   820  ### Stack栈
   821  
   822  EVM是基于栈的虚拟机,这里栈的作用是用来保存操作数的。
   823  
   824  ```
   825  // Stack is an object for basic stack operations. Items popped to the stack are
   826  // expected to be changed and modified. stack does not take care of adding newly
   827  // initialised objects.
   828  type Stack struct {
   829  	data []*big.Int
   830  }
   831  
   832  func newstack() *Stack {
   833  	return &Stack{data: make([]*big.Int, 0, 1024)}
   834  }
   835  
   836  func (st *Stack) push(d *big.Int) {
   837  	// NOTE push limit (1024) is checked in baseCheck
   838  	//stackItem := new(big.Int).Set(d)
   839  	//st.data = append(st.data, stackItem)
   840  	st.data = append(st.data, d)
   841  }
   842  
   843  func (st *Stack) pop() (ret *big.Int) {
   844  	ret = st.data[len(st.data)-1]
   845  	st.data = st.data[:len(st.data)-1]
   846  	return
   847  }
   848  ```
   849  
   850  ### Memory & stateDB
   851  
   852  Memery类为EVM实现了一个简单的内存模型。它主要在执行合约时针对operation进行一些内存里的参数拷贝。
   853  
   854  ```
   855  // Memory implements a simple memory model for the ethereum virtual machine.
   856  type Memory struct {
   857  	// 内存
   858  	store       []byte
   859  	// 最后一次的gas花费
   860  	lastGasCost uint64
   861  }
   862  
   863  // NewMemory returns a new memory memory model.
   864  func NewMemory() *Memory {
   865  	return &Memory{}
   866  }
   867  ```
   868  
   869  前面在创建合约账户的时候,将合约代码存储到了数据库。当创建合约失败的时候,也是利用数据库快照进行回滚状态的。
   870  
   871  ### 
   872  
   873  当有这样一段智能合约代码:
   874  
   875  ```
   876  pragma solidity ^0.4.0;
   877  contract SimpleStorage {
   878      uint storedData;
   879  
   880      function set(uint x) public {
   881          storedData = x;
   882      }
   883  
   884      function get() public returns (uint) {
   885          return storedData;
   886      }
   887  }
   888  ```
   889  
   890  在Remix编译器进行编译后得到字节码:
   891  
   892  ```
   893  {
   894  	"object": "606060405260a18060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360fe47b11460435780636d4ce63c14605d57603f565b6002565b34600257605b60048080359060200190919050506082565b005b34600257606c60048050506090565b6040518082815260200191505060405180910390f35b806000600050819055505b50565b60006000600050549050609e565b9056",
   895  	"opcodes": "PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0xA1 DUP1 PUSH1 0x10 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x60FE47B1 EQ PUSH1 0x43 JUMPI DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x5D JUMPI PUSH1 0x3F JUMP JUMPDEST PUSH1 0x2 JUMP JUMPDEST CALLVALUE PUSH1 0x2 JUMPI PUSH1 0x5B PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH1 0x82 JUMP JUMPDEST STOP JUMPDEST CALLVALUE PUSH1 0x2 JUMPI PUSH1 0x6C PUSH1 0x4 DUP1 POP POP PUSH1 0x90 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST DUP1 PUSH1 0x0 PUSH1 0x0 POP DUP2 SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 POP SLOAD SWAP1 POP PUSH1 0x9E JUMP JUMPDEST SWAP1 JUMP ",
   896  	"sourceMap": "24:189:0:-;;;;;;;;;",
   897  	"linkReferences": {}
   898  }
   899  ```
   900  
   901  其中,opcodes字段便是合约代码编译后的操作码集合。
   902  
   903  以PUSH1 0x60为例,可以在jump_table.go中找到对应的operation:
   904  
   905  ```
   906  PUSH1: {
   907  			execute:       makePush(1, 1),
   908  			gasCost:       gasPush,
   909  			validateStack: makeStackFunc(0, 1),
   910  			valid:         true,
   911  		}
   912  ```
   913  
   914  此时EVM就会去执行makePush函数,同时通过gasPush计算该操作需要的gas费用。EVM内部通过pop不断进行出栈操作来处理整个操作码集,当栈为空的时候表示整个合约代码执行完毕得到最后的执行结果。
   915  
   916  至此,有关EVM的源码研读就告一段落了。
   917  
   918